package com.njtoyo.taxi.admin.service.business.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njtoyo.taxi.admin.mapper.master.entity.DispFixedAddress;
import com.njtoyo.taxi.admin.mapper.master.entity.ElderlyDeviceManage;
import com.njtoyo.taxi.admin.mapper.master.mapper.ElderlyDeviceManageMapper;
import com.njtoyo.taxi.admin.rest.pojo.dto.ElderlyDeviceAddDto;
import com.njtoyo.taxi.admin.rest.pojo.dto.ElderlyDeviceFunctionUpdateDto;
import com.njtoyo.taxi.admin.rest.presenter.ElderlyDeviceCallCardNumPresenter;
import com.njtoyo.taxi.admin.rest.presenter.business.ElderlyDeviceManagePresenter;
import com.njtoyo.taxi.admin.rest.wrapper.business.device.ElderlyDeviceExportWrapper;
import com.njtoyo.taxi.admin.rest.wrapper.business.device.ElderlyDeviceQueryWrapper;
import com.njtoyo.taxi.admin.service.business.ElderlyDeviceService;
import com.njtoyo.taxi.admin.utils.DESede;
import com.njtoyo.taxi.entity.backend.AdminUser;
import com.taxi.entity.common.RestResult;
import com.taxi.entity.common.ResultEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ElderlyDeviceServiceImpl implements ElderlyDeviceService {

    private static final String ENCRYPT_KEY = "lSNjDx6Q4cV9P1OODznpExzB";

    private static final String IV = "20240101";

    private static final int TIME_OUT = 30000;

    private static final String BASE_URL = "https://taxi.njydi.cn/prod-api";

    private static final String FIX_UPDATE_URL = BASE_URL + "/extapi/xzw/fixedaddress?appId=9177257344&appSecret=&source=H5&version=1.0";

    @Resource
    private ElderlyDeviceManageMapper elderlyDeviceManageMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResult<Boolean> addNew(AdminUser adminUser,ElderlyDeviceAddDto dto) {
        //校验设备名称
        QueryWrapper<ElderlyDeviceManage> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("device_name",  dto.getDeviceName())
                .or().eq("sim_card",  dto.getSimCard()).or()
                .eq("device_serial_number",  dto.getDeviceSerialNumber());
        List<ElderlyDeviceManage> elderlyDeviceManages = elderlyDeviceManageMapper.selectList(queryWrapper);
        if(CollectionUtils.isNotEmpty(elderlyDeviceManages)){
            return RestResult.failed("设备名称/SIM卡号/设备序列号已存在,请重新输入",  ResultEnum.FAIL);
        }
        ElderlyDeviceManage elderlyDeviceManage = new ElderlyDeviceManage();
        elderlyDeviceManage.setDeviceName(dto.getDeviceName());
        elderlyDeviceManage.setDeviceAddress(dto.getDeviceAddress());
        elderlyDeviceManage.setDeviceId("ZL" + generateId());
        elderlyDeviceManage.setDeviceState(dto.getDeviceState());
        elderlyDeviceManage.setCantonId(dto.getCantonId());
        elderlyDeviceManage.setCantonName(dto.getCantonName());
        elderlyDeviceManage.setLongitude(dto.getLongitude());
        elderlyDeviceManage.setLatitude(dto.getLatitude());
        elderlyDeviceManage.setDeviceSerialNumber(dto.getDeviceSerialNumber());
        elderlyDeviceManage.setResponsibleName(dto.getResponsibleName());
        elderlyDeviceManage.setResponsiblePhone(dto.getResponsiblePhone());
        elderlyDeviceManage.setSimCard(dto.getSimCard());
        if(StringUtils.isNotBlank(dto.getRemark())){
            elderlyDeviceManage.setRemark(dto.getRemark());
        }
        elderlyDeviceManage.setUserId(adminUser.getId());
        elderlyDeviceManage.setUserName(adminUser.getName());
        elderlyDeviceManage.setCreateTime(new Date());
        elderlyDeviceManage.setUpdateTime(new Date());
        elderlyDeviceManageMapper.insert(elderlyDeviceManage);
        return RestResult.success();
    }

    @Override
    public RestResult<ElderlyDeviceManage> getElderlyDeviceByDeviceSerialNumber(String deviceSerialNumber) {
        LambdaQueryWrapper<ElderlyDeviceManage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ElderlyDeviceManage::getDeviceSerialNumber, deviceSerialNumber);
        ElderlyDeviceManage unEnable = elderlyDeviceManageMapper.selectOne(queryWrapper);
        if(ObjectUtils.isEmpty(unEnable)){
            return RestResult.failed("当前设备序列号不存在，请前往管理平台添加",  ResultEnum.NOT_FOUND);
        }
        return RestResult.success(unEnable);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResult<Boolean> enableElderlyByDevice(ElderlyDeviceAddDto dto) {
        LambdaQueryWrapper<ElderlyDeviceManage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ElderlyDeviceManage::getDeviceSerialNumber, dto.getDeviceSerialNumber());
        ElderlyDeviceManage elderlyDeviceManage = elderlyDeviceManageMapper.selectOne(queryWrapper);
        //启用
        elderlyDeviceManage.setDeviceState(1);
        elderlyDeviceManage.setEnableNumber(1);
        elderlyDeviceManage.setUpdateTime(new Date());
        elderlyDeviceManageMapper.update(elderlyDeviceManage, queryWrapper);
        return RestResult.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResult<Boolean> enableElderlyByBackend(ElderlyDeviceAddDto dto) {
        LambdaQueryWrapper<ElderlyDeviceManage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ElderlyDeviceManage::getDeviceId, dto.getDeviceId());
        ElderlyDeviceManage elderlyDeviceManage = elderlyDeviceManageMapper.selectOne(queryWrapper);
        if(ObjectUtils.isEmpty(elderlyDeviceManage)){
            return RestResult.failed("请确设备是否存在",  ResultEnum.NOT_FOUND);
        }
        Integer deviceState = dto.getDeviceState();
        if(1 == deviceState){
            //需要启用
            Integer enableNumber = elderlyDeviceManage.getEnableNumber();
            if(0 == enableNumber){
                return RestResult.failed("首次启用必须由设备终端启用",  ResultEnum.FAIL);
            }
            //是否有已启用的相同设备序列号
            queryWrapper.clear();
            queryWrapper.eq(ElderlyDeviceManage::getDeviceSerialNumber, elderlyDeviceManage.getDeviceSerialNumber());
            queryWrapper.eq(ElderlyDeviceManage::getDeviceState, 1);
            ElderlyDeviceManage res = elderlyDeviceManageMapper.selectOne(queryWrapper);
            if(ObjectUtils.isNotEmpty(res))
            {
                return RestResult.failed("已启用相同设备序列号的设备，请勿重复启用",  ResultEnum.FAIL);
            }
        }
        elderlyDeviceManage.setUpdateTime(new Date());
        elderlyDeviceManage.setDeviceState(deviceState);
        queryWrapper.clear();
        queryWrapper.eq(ElderlyDeviceManage::getDeviceId, dto.getDeviceId());
        elderlyDeviceManageMapper.update(elderlyDeviceManage, queryWrapper);
        //调用监管更新
        ElderlyDeviceManage nowManage = elderlyDeviceManageMapper.selectOne(queryWrapper);
        DispFixedAddress dispFixedAddress = new DispFixedAddress();
        dispFixedAddress.setFixedaddr(nowManage.getDeviceAddress());
        dispFixedAddress.setFixedcontenttell(nowManage.getResponsiblePhone());
        dispFixedAddress.setId(nowManage.getDeviceId());
        dispFixedAddress.setFixedname(nowManage.getDeviceName());
        dispFixedAddress.setFixedman(nowManage.getResponsibleName());
        dispFixedAddress.setState(nowManage.getDeviceState());
        dispFixedAddress.setLongitude(nowManage.getLongitude());
        dispFixedAddress.setLatitude(nowManage.getLatitude());
        dispFixedAddress.setImei(nowManage.getDeviceSerialNumber());
        dispFixedAddress.setSimno(nowManage.getSimCard());
        sendRequest(JSONObject.toJSONString(dispFixedAddress), FIX_UPDATE_URL);
        return RestResult.success();
    }

    @Override
    public RestResult<ElderlyDeviceManage> getInfo(String deviceSerialNumber) {
        LambdaQueryWrapper<ElderlyDeviceManage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ElderlyDeviceManage::getDeviceSerialNumber, deviceSerialNumber);
        ElderlyDeviceManage enable = elderlyDeviceManageMapper.selectOne(queryWrapper);
        return RestResult.success(enable);
    }

    @Override
    public RestResult<Boolean> editElderlyDevice(AdminUser adminUser, ElderlyDeviceAddDto dto) {
        Integer deviceState = dto.getDeviceState();
        LambdaQueryWrapper<ElderlyDeviceManage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ElderlyDeviceManage::getDeviceName, dto.getDeviceName()).ne(ElderlyDeviceManage::getDeviceId, dto.getDeviceId());
        ElderlyDeviceManage deviceNameResult = elderlyDeviceManageMapper.selectOne(queryWrapper);
        if(ObjectUtils.isNotEmpty(deviceNameResult)){
            return RestResult.failed("当前设备名称已存在,请重新输入",  ResultEnum.FAIL);
        }
        queryWrapper.clear();
        queryWrapper.eq(ElderlyDeviceManage::getDeviceSerialNumber, dto.getDeviceSerialNumber())
                .ne(ElderlyDeviceManage::getDeviceId, dto.getDeviceId());
        ElderlyDeviceManage deviceSerialNumberResult = elderlyDeviceManageMapper.selectOne(queryWrapper);
        if(ObjectUtils.isNotEmpty(deviceSerialNumberResult)){
            return RestResult.failed("当前设备序列号已存在,请重新输入",  ResultEnum.FAIL);
        }
        queryWrapper.clear();
        queryWrapper.eq(ElderlyDeviceManage::getSimCard, dto.getSimCard())
                .ne(ElderlyDeviceManage::getDeviceId, dto.getDeviceId());
        ElderlyDeviceManage simCardResult = elderlyDeviceManageMapper.selectOne(queryWrapper);
        if(ObjectUtils.isNotEmpty(simCardResult)){
            return RestResult.failed("当前SIM卡号已存在,请重新输入",  ResultEnum.FAIL);
        }
        /*if(1 == deviceState){
           //启用
            queryWrapper.clear();;
            queryWrapper.eq(ElderlyDeviceManage::getDeviceSerialNumber, dto.getDeviceSerialNumber());
            queryWrapper.eq(ElderlyDeviceManage::getDeviceState, 1);
            ElderlyDeviceManage enable = elderlyDeviceManageMapper.selectOne(queryWrapper);
            if(ObjectUtils.isNotEmpty(enable)){
                return RestResult.failed("当前设备序列号" + dto.getDeviceSerialNumber() +  "已启用,请更换",  ResultEnum.FAIL);
            }
        }*/
        dto.setUpdateTime(new Date());
        elderlyDeviceManageMapper.updateElderlyDevice(dto);
        //调用监管更新
        queryWrapper.clear();
        queryWrapper.eq(ElderlyDeviceManage::getDeviceId, dto.getDeviceId());
        ElderlyDeviceManage nowManage = elderlyDeviceManageMapper.selectOne(queryWrapper);
        DispFixedAddress dispFixedAddress = new DispFixedAddress();
        dispFixedAddress.setFixedaddr(nowManage.getDeviceAddress());
        dispFixedAddress.setFixedcontenttell(nowManage.getResponsiblePhone());
        dispFixedAddress.setId(nowManage.getDeviceId());
        dispFixedAddress.setFixedname(nowManage.getDeviceName());
        dispFixedAddress.setFixedman(nowManage.getResponsibleName());
        dispFixedAddress.setState(nowManage.getDeviceState());
        dispFixedAddress.setLongitude(nowManage.getLongitude());
        dispFixedAddress.setLatitude(nowManage.getLatitude());
        dispFixedAddress.setImei(nowManage.getDeviceSerialNumber());
        dispFixedAddress.setSimno(nowManage.getSimCard());
        sendRequest(JSONObject.toJSONString(dispFixedAddress), FIX_UPDATE_URL);
        return RestResult.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResult<Boolean> updateElderlyDeviceFunction(ElderlyDeviceFunctionUpdateDto dto) {
        elderlyDeviceManageMapper.updateElderlyDeviceFunction(dto);
        return RestResult.success();
    }

    @Override
    public RestResult<Page<ElderlyDeviceManagePresenter>> getList(AdminUser adminUser, ElderlyDeviceQueryWrapper wrapper) {
        Page<ElderlyDeviceManagePresenter> elderlyPage = elderlyDeviceManageMapper.queryAll(wrapper);
        List<ElderlyDeviceManagePresenter> records = elderlyPage.getRecords();
        if(CollectionUtils.isNotEmpty(records)){
            for (ElderlyDeviceManagePresenter record : records) {
                String deviceSerialNumber = record.getDeviceSerialNumber();
                Integer callNum = elderlyDeviceManageMapper.queryCountCall(deviceSerialNumber);
                //呼叫
                record.setCallNumber(callNum);
                Integer ridePick = elderlyDeviceManageMapper.queryCountCallRidePick(deviceSerialNumber);
                record.setRidePickCount(ridePick);
                List<ElderlyDeviceCallCardNumPresenter> callCardNum = elderlyDeviceManageMapper.getCallCardNum(deviceSerialNumber);
                record.setCallCardNum(callCardNum);
            }
        }
        return RestResult.success(elderlyPage);
    }

    @Override
    public RestResult<List<ElderlyDeviceCallCardNumPresenter>> getCallCardNum(String deviceSerialNumber) {
        List<ElderlyDeviceCallCardNumPresenter> callCardNum = elderlyDeviceManageMapper.getCallCardNum(deviceSerialNumber);
        return RestResult.success(callCardNum);
    }

    @Override
    public void exportElderlyDeviceList(AdminUser adminUser, ElderlyDeviceExportWrapper wrapper, HttpServletResponse response) throws IOException {
        List<ElderlyDeviceManagePresenter> exportList = elderlyDeviceManageMapper.queryAllElderlyDevice(wrapper);
        if(CollectionUtils.isNotEmpty(exportList)){
            exportList = exportList.stream().filter(item -> {
                String deviceSerialNumber = item.getDeviceSerialNumber();
                Integer callNum = elderlyDeviceManageMapper.queryCountCall(deviceSerialNumber);
                //呼叫
                item.setCallNumber(callNum);
                Integer ridePick = elderlyDeviceManageMapper.queryCountCallRidePick(deviceSerialNumber);
                item.setRidePickCount(ridePick);
                return true;
            }).collect(Collectors.toList());
        }
        String fileName = URLEncoder.encode("助老设备信息", "UTF-8").replaceAll("\\+", "%20");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), ElderlyDeviceManagePresenter.class)
                .sheet()
                .doWrite(exportList);
    }

    @Override
    public RestResult<ElderlyDeviceCallCardNumPresenter> getAllCallCardNumPresenter() {
        ElderlyDeviceCallCardNumPresenter allDeviceCallNum = elderlyDeviceManageMapper.getAllDeviceCallNum();
        return RestResult.success(allDeviceCallNum);
    }

    @Override
    public RestResult<List<ElderlyDeviceManagePresenter>> getListByCantonId(Integer cantonId) {
        List<ElderlyDeviceManagePresenter> allElderlyDevice = elderlyDeviceManageMapper.queryAllElderlyDeviceByCantonId(cantonId);
        if(CollectionUtils.isNotEmpty(allElderlyDevice)){
            for (ElderlyDeviceManagePresenter record : allElderlyDevice) {
                String deviceSerialNumber = record.getDeviceSerialNumber();
                Integer callNum = elderlyDeviceManageMapper.queryCountCall(deviceSerialNumber);
                //呼叫
                record.setCallNumber(callNum);
                Integer ridePick = elderlyDeviceManageMapper.queryCountCallRidePick(deviceSerialNumber);
                record.setRidePickCount(ridePick);
            }
        }
        return RestResult.success(allElderlyDevice);
    }

    public String generateId()
    {
        Random random = new Random();
        int randomNum = 100000 + random.nextInt(900000);
        LocalDate today = LocalDate.now();
        String dateStr = String.format("%04d%02d%02d",
                today.getYear(), today.getMonthValue(), today.getDayOfMonth());
        return randomNum + dateStr;
    }

    public void sendRequest(String request, String url)
    {
        String data = DESede.encrypt(ENCRYPT_KEY, IV, request);
        log.info("device update url : {}, json : {}, data : {}", url, request, data);
        try (HttpResponse response = HttpUtil.createPost(url).timeout(TIME_OUT).body(data).execute()) {
            log.info("device update url : {} response : {}", url, response.body());
        }
    }
}
